import { nextTick, ref, unref } from "vue"
import { isEmptyVal } from "@/utils/is"
import type { ElForm } from 'element-plus'
import type { ExtendedDynamicForm } from "@/components/DynamicForm"
import type { FormSetProps } from "@/components/DynamicForm/src/types"

export const useForm = () => {
  const formRef = ref<ExtendedDynamicForm | null>()
  const elFormRef = ref<InstanceType<typeof ElForm>>()
  const register = (ref: ExtendedDynamicForm, elRef: InstanceType<typeof ElForm>) => {
    formRef.value = ref
    elFormRef.value = elRef
  }

  const getForm = async () => {
    await nextTick()
    const form = unref(formRef)

    if (!form) {
      console.error('The form is not registered. Please use the register method to register')
    }
    return form
  }

  // 一些内置的方法
  const methods = {
    /**
     * @description 设置form的值
     * @param data 需要设置的数据
     */
    setValues: async (data: Record<string, any>) => {
      const form = await getForm()
      form?.setValues(data)
    },

    /**
     * @description 设置schema
     * @param schemaProps 需要设置的schemaProps
     */
    setSchema: async (schemaProps: FormSetProps[]) => {
      const form = await getForm()
      if (form && typeof form.setSchema === "function") {
        form.setSchema(schemaProps);
      } else {
        console.error("The form does not have a setSchema method.");
      }
    },

    /**
     * @description 获取表单数据
     * @returns form data
     */
    getFormData: async <T = Record<string, any>>(filterEmptyVal = true): Promise<T> => {
      const form = await getForm()
      const model = form?.formModel as any

      if (filterEmptyVal) {
        // 使用 reduce 过滤空值，并返回一个新对象
        return Object.keys(model).reduce((prev, next) => {
          const value = model[next]
          if (!isEmptyVal(value)) {
            prev[next] = value
          }
          return prev
        }, {} as Record<string, any>) as T
      } else {
        return model as T
      }
    },

    /**
     * @description 获取ElForm组件的实例
     * @returns ElForm instance
     */
    getElFormExpose: async () => {
      await getForm()
      return unref(elFormRef)
    }
  }

  return {
    formRegister: register,
    formMethods: methods
  }
}
